package com.lhl.fw.db.entity;

import com.vladmihalcea.hibernate.type.array.IntArrayType;
import com.vladmihalcea.hibernate.type.array.StringArrayType;
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import com.vladmihalcea.hibernate.type.json.JsonNodeBinaryType;
import com.vladmihalcea.hibernate.type.json.JsonNodeStringType;
import com.vladmihalcea.hibernate.type.json.JsonStringType;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.annotations.*;
import org.springframework.data.domain.AfterDomainEventPublication;
import org.springframework.data.domain.DomainEvents;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author king
 */
@TypeDefs({
        @TypeDef(name = "string-array", typeClass = StringArrayType.class),
        @TypeDef(name = "int-array", typeClass = IntArrayType.class),
        @TypeDef(name = "json", typeClass = JsonStringType.class),
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class),
        @TypeDef(name = "jsonb-node", typeClass = JsonNodeBinaryType.class),
        @TypeDef(name = "json-node", typeClass = JsonNodeStringType.class),
})
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Getter
@Setter
@EqualsAndHashCode(callSuper = true)
@Slf4j
@SelectBeforeUpdate
@DynamicInsert
@DynamicUpdate
@Polymorphism(type = PolymorphismType.EXPLICIT)
@OptimisticLocking (type = OptimisticLockType.ALL)
public abstract class BaseEntity<ID extends Serializable> extends AbstractEntity<ID> {

    /**
     * @fields serialVersionUID
     */
    @SuppressWarnings("unused")
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(generator = "idGenerator")
    @GenericGenerator(name = "idGenerator", strategy = "uuid")
    @Column(name = "ID", length = 32)
    @NotNull(groups = {Update.class})
    @ApiModelProperty(value = "主键", hidden = true)
    private ID id;

    /**
     * 版本
     */
    @Version
    @Column(name = "VERSION")
    @ApiModelProperty(value = "版本", hidden = true)
    private Long version;

    /* 分组校验 */
    public @interface Create {
    }

    /* 分组校验 */
    public @interface Update {
    }

    /**
     * @param:
     * @description: 使用集合类注册事件列表
     * @return: java.util.Collection<java.lang.Object>
     * @author: king
     * @date: 2020-11-06
     */
    @DomainEvents
    public List<Object> domainEvents() {
        log.debug("DDD开始被调用");
        List<Object> list = Arrays.asList(this);
        List events = new ArrayList(list);
        return events;
    }

    /**
     * @description: 所有事件发布完成后调用，一般用来清空事件列表
     * @return:
     * @author: king
     * @date: 2020-11-06
     */
    @AfterDomainEventPublication
    public void callbackMethod() {
        log.debug("DDD清楚事件");
        domainEvents().clear();
    }
}
